import random
import time, json
from Cryptodome.PublicKey import RSA
from base64 import b64encode
from Cryptodome.Signature import pkcs1_15
from Cryptodome.Hash import SHA256
import requests
import datetime

# 微信支付商户号
MCHID = '1624049247'
# 商户证书私钥
with open('../webService/cert/apiclient_key.pem') as f:
    PRIVATE_KEY = f.read()
# 商户证书序列号
CERT_SERIAL_NO = '3E951632C4ED6849FF3680F6B9E85CCF99D453AB'
# API v3密钥， https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_2.shtml
APIV3_KEY = 'def33fdscnu3595fr4f4jf4l23n2l3f3'
# APPID
APPID = 'wxd9cfdc38b3bf4c23'
# 回调地址，也可以在调用接口的时候覆盖
NOTIFY_URL = 'http://2b270619d7.iask.in/notify'
# 微信支付平台证书缓存目录
CERT_DIR = './cert'


def random_str(lengh=32):
    """
    生成随机字符串，提供给支付接口使用
    :return :32位随机字符串
    """
    now_time = datetime.datetime.now()
    re_time = datetime.datetime.strftime(now_time, '%Y-%m-%d %H:%M:%S')
    timeint = re_time.replace("-", "").replace(":", "").replace(" ", "")
    chars = 'abcdefghijklmnopqrstuvwxyz0123456789'
    rand = random.Random()
    return "".join([chars[rand.randint(0, len(chars) - 1)] for i in range(lengh - 14)])


# 统一下单
def pay_order(wx_id, fee):
    out_trade_no = random_str(32)
    """
    统一下单
    https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml
    """
    url = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi"
    data = {
        'appid': APPID,
        'mchid': MCHID,
        'description': "商品付款",
        'out_trade_no': out_trade_no,
        'notify_url': NOTIFY_URL,
        'amount': {
            'total': fee,
            'currency': "CNY",
        },
        'payer': {
            'openid': wx_id
        }
    }
    timestamp = str(int(time.time()))
    nonceStr = random_str(32)

    # 制作加密请求头
    signature = _generate_request_sign(url_path="/v3/pay/transactions/jsapi", data=data, timestamp=timestamp,
                                       nonceStr=nonceStr)
    headers = {'Authorization': _generate_auth_header(signature, timestamp, nonceStr)}

    message = requests.post(url=url, headers=headers, json=data).text

    messagedict = json.loads(message)  # 拿到 prepay_id
    # print(messagedict)

    # 生成pay_sign支付签名；再将页面所有需要信息打包返回
    ret_params = sign_reply(app_id=APPID, prepay_id=messagedict["prepay_id"], timestamp=timestamp, nonceStr=nonceStr)
    ret_params["fee"] = fee / 100
    ret_params["out_trade_no"] = out_trade_no
    return ret_params


def _generate_request_sign(url_path, data, timestamp, nonceStr, method='POST'):
    """
    生成请求签名，SHA256进行加密
    """
    sign_list = [method, url_path, timestamp, nonceStr]
    if data is not None:
        sign_list.append(json.dumps(data))
    else:
        sign_list.append('')
    sign_str = '\n'.join(sign_list) + '\n'

    rsa_key = RSA.import_key(PRIVATE_KEY)
    signer = pkcs1_15.new(rsa_key)
    digest = SHA256.new(sign_str.encode('utf-8'))
    return b64encode(signer.sign(digest)).decode('utf-8')


def _generate_auth_header(signature, timestamp, nonceStr):
    """
    生成授权请求头
    """
    return f'WECHATPAY2-SHA256-RSA2048  mchid="{MCHID}",nonce_str="{nonceStr}",' \
           f'signature="{signature}",timestamp="{timestamp}",serial_no="{CERT_SERIAL_NO}"'


def sign_reply(app_id, prepay_id, timestamp, nonceStr):
    """
    生成支付签名
    """
    # timestamp = str(int(time.time()))
    # nonceStr = random_str(32)
    sign_list = [app_id, timestamp, nonceStr, "prepay_id=" + prepay_id]
    sign_str = '\n'.join(sign_list) + '\n'

    """
    生成签名值sign
    private_key_path 私钥路径
    sign_str 签名字符串
    https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_0.shtml
    """
    try:
        rsa_key = RSA.import_key(PRIVATE_KEY)
        signer = pkcs1_15.new(rsa_key)
        digest = SHA256.new(sign_str.encode('utf-8'))
        pay_sign = b64encode(signer.sign(digest)).decode('utf-8')
    except Exception as e:
        raise e

    return {
        'app_id': app_id,
        'timestamp': timestamp,
        'nonceStr': nonceStr,
        'package': 'prepay_id=' + prepay_id,
        'sign_type': 'RSA',
        'pay_sign': pay_sign
    }


def transfers(openid, amount):
    """
    : partner_trade_no: 提现处理编号
    : openid: 提现用户识别号
    : amount: 提现金额
    """
    url = "https://api.mch.weixin.qq.com/v3/transfer/batches"

    out_trade_no = random_str(32)
    money = int(round(amount, 2) * 100)
    data = {
        "appid": APPID,
        "out_batch_no": out_trade_no,
        "batch_name": "返利转账",
        "batch_remark": "返利转账",
        "total_amount": money,
        "total_num": 1,
        "transfer_detail_list": [
            {
                "out_detail_no": out_trade_no,
                "transfer_amount": money,
                "transfer_remark": "返利转账",
                "openid": openid
            }
        ]
    }
    timestamp = str(int(time.time()))
    nonceStr = random_str(32)

    signature = _generate_request_sign(url_path="/v3/transfer/batches", data=data, timestamp=timestamp,
                                       nonceStr=nonceStr)
    headers = {'Authorization': _generate_auth_header(signature, timestamp, nonceStr)}

    message = requests.post(url=url, headers=headers, json=data).text
    return message


if __name__ == "__main__":
    # prepay_id = pay_order(wx_id='oxVH76qz2we4yyk-RaGrgpv8eIZE',fee=2)

    # message = transfers(openid="oxVH76qz2we4yyk-RaGrgpv8eIZE", amount=1)
    # print(message)
    pass
